package com.kingbook.core.utils;

import com.kingbook.common.enums.JavaType;
import com.kingbook.common.utils.DateUtils;
import com.kingbook.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.support.JdbcUtils;

import java.math.BigDecimal;
import java.sql.*;

import static com.kingbook.common.enums.DateFormatEnum.*;

public class JDBCHelper {

    protected static Logger logger = LoggerFactory.getLogger(JDBCHelper.class);

    public static Object getFormatResult(ResultSet rs, int index) throws SQLException {
        Object obj = rs.getObject(index);
        Class clazz = null;
        if (obj != null) {
            clazz = obj.getClass();
        }
        if (Blob.class.equals(clazz) || byte[].class.equals(clazz)) {
            return rs.getBytes(index);
        } else if (Clob.class.equals(clazz) || String.class.equals(clazz)) {
            return rs.getString(index);
        } else if (boolean.class.equals(clazz) || Boolean.class.equals(clazz)) {
            return rs.getBoolean(index);
        } else if (byte.class.equals(clazz) || Byte.class.equals(clazz)) {
            return rs.getByte(index);
        } else if (short.class.equals(clazz) || Short.class.equals(clazz)) {
            return rs.getShort(index);
        } else if (int.class.equals(clazz) || Integer.class.equals(clazz)) {
            return rs.getInt(index);
        } else if (long.class.equals(clazz) || Long.class.equals(clazz)) {
            return rs.getLong(index);
        } else if (float.class.equals(clazz) || Float.class.equals(clazz)) {
            return rs.getFloat(index);
        } else if (double.class.equals(clazz) || Double.class.equals(clazz) || Number.class.equals(clazz)) {
            return rs.getDouble(index);
        } else if (BigDecimal.class.equals(clazz)) {
            return rs.getBigDecimal(index);
        } else if (Date.class.equals(clazz)) {
            return DateUtils.format(rs.getDate(index), DATE);
        } else if (Time.class.equals(clazz)) {
            return DateUtils.format(rs.getTime(index), TIME);
        } else if (Timestamp.class.equals(clazz) || java.util.Date.class.equals(clazz)) {
            return DateUtils.format(rs.getTimestamp(index), DATETIME);
        } else {
            return obj == null ? "" : JdbcUtils.getResultSetValue(rs, index);
        }
    }

    public static Object getObjectResult(ResultSet rs, int index) throws SQLException {
        Object obj = rs.getObject(index);
        Class clazz = null;
        if (obj != null) {
            clazz = obj.getClass();
        }
        if (Blob.class.equals(clazz) || byte[].class.equals(clazz)) {
            return rs.getBytes(index);
        } else if (Clob.class.equals(clazz) || String.class.equals(clazz)) {
            return rs.getString(index);
        } else if (boolean.class.equals(clazz) || Boolean.class.equals(clazz)) {
            return rs.getBoolean(index);
        } else if (byte.class.equals(clazz) || Byte.class.equals(clazz)) {
            return rs.getByte(index);
        } else if (short.class.equals(clazz) || Short.class.equals(clazz)) {
            return rs.getShort(index);
        } else if (int.class.equals(clazz) || Integer.class.equals(clazz)) {
            return rs.getInt(index);
        } else if (long.class.equals(clazz) || Long.class.equals(clazz)) {
            return rs.getLong(index);
        } else if (float.class.equals(clazz) || Float.class.equals(clazz)) {
            return rs.getFloat(index);
        } else if (double.class.equals(clazz) || Double.class.equals(clazz) || Number.class.equals(clazz)) {
            return rs.getDouble(index);
        } else if (BigDecimal.class.equals(clazz)) {
            return rs.getBigDecimal(index);
        } else if (Date.class.equals(clazz)) {
            return rs.getDate(index);
        } else if (Time.class.equals(clazz)) {
            return rs.getTime(index);
        } else if (Timestamp.class.equals(clazz) || java.util.Date.class.equals(clazz)) {
            return rs.getTimestamp(index);
        } else {
            return obj == null ? null : JdbcUtils.getResultSetValue(rs, index);
        }
    }

    // TODO: 2019/2/13 add oracle type 
    public static JavaType toJavaType(String jdbcType) {
        jdbcType = StringUtils.isNotEmpty(jdbcType) ? jdbcType.toUpperCase() : "";
        if (match(jdbcType, "TINYINT", "SMALLINT", "MEDIUMINT", "INT")) {
            return JavaType.INTEGER;
        } else if (match(jdbcType, "ID", "INTEGER", "BIGINT", "NUMBER")) {
            return JavaType.LONG;
        } else if (match(jdbcType, "FLOAT", "REAL")) {
            return JavaType.FLOAT;
        } else if (match(jdbcType, "DOUBLE")) {
            return JavaType.DOUBLE;
        } else if (match(jdbcType, "DECIMAL", "NUMERIC")) {
            return JavaType.BIGDECIMAL;
        } else if (match(jdbcType, "BIT")) {
            return JavaType.BOOLEAN;
        } else if (match(jdbcType, "DATETIME", "TIMESTAMP")) {
            return JavaType.TIMESTAMP;
        } else if (match(jdbcType, "YEAR", "DATE")) {
            return JavaType.DATE;
        } else if (match(jdbcType, "TIME")) {
            return JavaType.TIME;
        } else if (match(jdbcType, "TINYBLOB", "BLOB", "MEDIUMBLOB", "LONGBLOB", "BINARY", "VARBINARY")) {
            return JavaType.BYTE_ARRAY;
        } else if (match(jdbcType, "CHAR", "VARCHAR", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT", "CLOB", "ENUM", "SET", "VARCHAR2")) {
            return JavaType.STRING;
        }
        logger.info("未找到类型:{}", jdbcType);
        return JavaType.UNKNOW;
    }


    static boolean match(String p, String... str) {
        for (String s : str) {
            if (p.startsWith(s))
                return true;
        }
        return false;
    }

    public static void cleanup(Connection conn, Statement st, ResultSet rs) {
        try {
            if (rs != null && !rs.isClosed()) {
                rs.close();
            }
        } catch (SQLException e) {
            logger.trace("关闭数据库结果集异常 ", e);
        }

        try {
            if (st != null && !st.isClosed()) {
                st.close();
            }
        } catch (SQLException e) {
            logger.trace("关闭数据库操作语句异常 ", e);
        }

        try {
            if (conn != null && !conn.isClosed()) {
                conn.close();
            }
        } catch (SQLException e) {
            logger.trace("关闭数据库连接异常 ", e);
        }

    }
}
